package com.zjl.redis.第15章_缓存预热_雪崩_击穿_穿透;

import cn.hutool.bloomfilter.BitMapBloomFilter;
import cn.hutool.bloomfilter.BloomFilter;

/**
 * 缓存穿透
 * redis命中率降低
 * 一直查数据库
 * 缓存穿透：出现的情况
 *     1.redis查询不到数据，redis命中率降低
 *     2.出现很多非正常的url访问//如恶意攻击
 *
 * 缓存穿透出现的情况
 *  一个一定不存在缓存及查询不到的数据,于缓存是不命中时被动写的,
 *  并且出于容错考虑,如果从存储层查不到数据则不写入缓存,
 *  这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。
 * 解决方案:
 * (1) 对空值缓存:   只要对付正常情况，无法防止黑客会对你的系统进行攻击，进行大量不存在的请求访问
 *      如果一个查询返回的数据为空(不管是数据是否不存在)，
 *      我们仍然把这个空结果(null)进行缓存，
 *      设置空结果的过期时间会很短,最长不超过五分钟，
 * (2) 设置可访问的名单(白名单)。也可以用布隆过滤器
 *      使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,
 *      每次访问和bitmap里面的id进行比较,如果访问id不在bitmaps里面,进行拦截，不允许访问。
 * (3)采用布隆过滤器:
 *      布隆过滤器( Bloom Filter) 是1970年由布隆提出的。
 *      它实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数)。
 *      布隆过滤器可以用于检索-个元素是否在一个集合中。
 *      它的优点是空间效率和查询时间都远远超过一般的算法,
 *      缺点是有一定的误识别率和删除困难。
 *      将所有可能存在的数据哈希到一个足够大的bitmaps中，一个一定不存在
 *      的数据会被这个bitmaps拦截掉,从而避免了对底层存储系统的查询压力。
 *      @see com.zjl.redis.第14章_大数据统计.C3_布隆过滤器底层
 * (4)进行实时监控:当发现Redis的命中开始急速降低,
 *      需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名单限制服务。
 */
public class B_缓存穿透 {

    //m 不能太大 ，很占空间
    static BloomFilter bloomFilter = new BitMapBloomFilter(10);
    //hutool   工具包
    public static void main(String[] args) {

        int mun = 0;
        for (int i = 0; i < 1000000; i++) {
            if(!bloomFilter.add(i+"")){
                System.out.println(i);
                mun++;
            }
        }
        System.out.println("误判了：" + mun + "个数据");

    }
}